﻿#region Honorbuddy

#endregion

#region System

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows.Documents;
using System.Windows.Media;
using CommonBehaviors.Actions;
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;

#endregion

namespace Simcraft
{

    public partial class SimcraftImpl
    {


        public class BuffProxy
        {
            public class BuffInternal
            {
                private string _name;
                private int spellid = 0;

                public BuffInternal(string name)
                {
                    this._name = name;
                }
                public BuffInternal(int spellid)
                {
                    this.spellid = spellid;
                }
                public bool Down
                {
                    get
                    {
                        return spellid == 0
                            ? GetAuraTimeLeft(StyxWoW.Me.ToUnit(), _name) == TimeSpan.Zero
                            : GetAuraTimeLeft(StyxWoW.Me.ToUnit(), spellid) == TimeSpan.Zero;
                    }
                }

                public bool Up
                {
                    get
                    {
                        return spellid == 0
                            ? GetAuraTimeLeft(StyxWoW.Me.ToUnit(), _name) != TimeSpan.Zero
                            : GetAuraTimeLeft(StyxWoW.Me.ToUnit(), spellid) != TimeSpan.Zero;
                    }
                }

                public int Stack
                {
                    get
                    {
                        return spellid == 0
                            ? GetAuraStacks(StyxWoW.Me.ToUnit(), _name)
                            : GetAuraStacks(StyxWoW.Me.ToUnit(), spellid);
                    }
                }

                public double Remains
                {
                    get
                    {
                        return spellid == 0
                            ? GetAuraTimeLeft(StyxWoW.Me.ToUnit(), _name).TotalSeconds
                            : GetAuraTimeLeft(StyxWoW.Me.ToUnit(), spellid).TotalSeconds;
                    }
                }
            }

            Dictionary<string, BuffInternal> itemsByName = new Dictionary<string, BuffInternal>();
            Dictionary<int, BuffInternal> itemsById = new Dictionary<int, BuffInternal>();

            public BuffInternal this[String name]
            {
                get
                {
                    if (!itemsByName.ContainsKey(name)) itemsByName.Add(name, new BuffInternal(name));
                    return itemsByName[name];
                }
            }

            public BuffInternal this[int id]
            {
                get
                {
                    if (!itemsById.ContainsKey(id)) itemsById.Add(id, new BuffInternal(id));
                    return itemsById[id];
                }
            }

        }

        public class CooldownProxy
        {
            public class CooldownInternal
            {
                private string _name;
                private int spellid = 0;

                public CooldownInternal(string name)
                {
                    this._name = name;
                }
                public CooldownInternal(int spellid)
                {
                    this.spellid = spellid;
                }
                public bool Down
                {
                    get
                    {
                        return spellid == 0
                            ? GetSpellOnCooldown(_name)
                            : GetSpellOnCooldownId(spellid);
                    }
                }

                public bool Up
                {
                    get
                    {
                        return spellid == 0
                            ? !GetSpellOnCooldown(_name)
                            : !GetSpellOnCooldownId(spellid);
                    }
                }


                public double Remains
                {
                    get
                    {
                        return spellid == 0
                            ? GetSpellCooldown(_name).TotalSeconds
                            : GetSpellCooldownId(spellid).TotalSeconds;
                    }
                }

            }

            Dictionary<string, CooldownInternal> itemsByName = new Dictionary<string, CooldownInternal>();
            Dictionary<int, CooldownInternal> itemsById = new Dictionary<int, CooldownInternal>();

            public CooldownInternal this[String name]
            {
                get
                {
                    if (!itemsByName.ContainsKey(name)) itemsByName.Add(name, new CooldownInternal(name));
                    return itemsByName[name];
                }
            }

            public CooldownInternal this[int id]
            {
                get
                {
                    if (!itemsById.ContainsKey(id)) itemsById.Add(id, new CooldownInternal(id));
                    return itemsById[id];
                }
            }

        }

        public class SpellProxy
        {
            public class SpellInternal
            {
                private string _name;
                private int spellid = 0;

                public SpellInternal(string name)
                {
                    this._name = name;
                }

                public SpellInternal(int spellid)
                {
                    this.spellid = spellid;
                }

                public int Charges
                {
                    get
                    {
                        return spellid == 0
                            ? Lua.GetReturnVal<int>(
                                "currentCharges,_,_,_,_ = GetSpellCharges(\"" + _name + "\"); return currentCharges", 0)
                            : Lua.GetReturnVal<int>(
                                "currentCharges,_,_,_,_ = GetSpellCharges(" + spellid + "); return currentCharges", 0);
                    }
                }

                public int CastTime
                {
                    get
                    {
                        return spellid == 0
                            ? (int)GetSpell(_name).CastTime
                            : (int)GetSpell(spellid).CastTime;
                    }
                }

                public double ChannelTime
                {
                    get
                    {
                        return spellid == 0
                            ? (int)GetSpell(_name).BaseDuration / 1000
                            : (int)GetSpell(spellid).BaseDuration / 1000;
                    }
                }

                public double RechargeTime
                {
                    get
                    {
                        return spellid == 0
                            ? Lua.GetReturnVal<double>(
                                "currentCharges, maxCharges, cooldownStart, cooldownDuration = GetSpellCharges(\"" +
                                _name + "\"); cd = (cooldownDuration-(GetTime()-cooldownStart)); if (cd > cooldownDuration or cd < 0) then cd = 0; end return cd", 0)
                            : Lua.GetReturnVal<double>(
                                "currentCharges, maxCharges, cooldownStart, cooldownDuration = GetSpellCharges(\"" +
                                spellid + "\"); cd = (cooldownDuration-(GetTime()-cooldownStart)); if (cd > cooldownDuration or cd < 0) then cd = 0; end return cd", 0);
                        /*           "currentCharges, maxCharges, cooldownStart, cooldownDuration = GetSpellCharges("Roll"); cd = (cooldownDuration-(GetTime()-cooldownStart)); if (cd > cooldownDuration or cd < 0) then cd = 0; end return cd", 0);*/
                        /*/script currentCharges, maxCharges, cooldownStart, cooldownDuration = GetSpellCharges("Roll"); return (GetTime()-cooldownStart);*/
                        /*/script currentCharges, maxCharges, cooldownStart, cooldownDuration = GetSpellCharges("Roll"); cd = (cooldownDuration-(GetTime()-cooldownStart)); if (cd > cooldownDuration or cd < 0) then cd = 0; end*/
                    }
                }

            }

            Dictionary<string, SpellInternal> itemsByName = new Dictionary<string, SpellInternal>();
            Dictionary<int, SpellInternal> itemsById = new Dictionary<int, SpellInternal>();

            public SpellInternal this[String name]
            {
                get
                {
                    if (!itemsByName.ContainsKey(name)) itemsByName.Add(name, new SpellInternal(name));
                    return itemsByName[name];
                }
            }

            public SpellInternal this[int id]
            {
                get
                {
                    if (!itemsById.ContainsKey(id)) itemsById.Add(id, new SpellInternal(id));
                    return itemsById[id];
                }
            }

        }

        public class DebuffProxy
        {

            public class DebuffInternal
            {
                private string _name;
                private int spellid = 0;

                public DebuffInternal(string name)
                {
                    this._name = name;
                }
                public DebuffInternal(int spellid)
                {
                    this.spellid = spellid;
                }
                public bool Down
                {
                    get
                    {
                        return spellid == 0
                            ? GetAuraTimeLeft(StyxWoW.Me.CurrentTarget, _name, true) == TimeSpan.Zero
                            : GetAuraTimeLeft(StyxWoW.Me.CurrentTarget, spellid, true) == TimeSpan.Zero;
                    }
                }

                public bool Up
                {
                    get
                    {
                        return spellid == 0
                            ? GetAuraTimeLeft(StyxWoW.Me.CurrentTarget, _name, true) != TimeSpan.Zero
                            : GetAuraTimeLeft(StyxWoW.Me.CurrentTarget, spellid, true) != TimeSpan.Zero;
                    }
                }

                public int Stack
                {
                    get
                    {
                        return spellid == 0
                            ? GetAuraStacks(StyxWoW.Me.CurrentTarget, _name, true)
                            : GetAuraStacks(StyxWoW.Me.CurrentTarget, spellid, true);
                    }
                }

                public double Remains
                {
                    get
                    {
                        return spellid == 0
                            ? GetAuraTimeLeft(StyxWoW.Me.CurrentTarget, _name, true).TotalSeconds
                            : GetAuraTimeLeft(StyxWoW.Me.CurrentTarget, spellid, true).TotalSeconds;
                    }
                }
            }


            Dictionary<string, DebuffInternal> DebuffsByName = new Dictionary<string, DebuffInternal>();
            Dictionary<int, DebuffInternal> DebuffsById = new Dictionary<int, DebuffInternal>();

            public DebuffInternal this[String name]
            {
                get
                {
                    if (!DebuffsByName.ContainsKey(name)) DebuffsByName.Add(name, new DebuffInternal(name));
                    return DebuffsByName[name];
                }
            }

            public DebuffInternal this[int id]
            {
                get
                {
                    if (!DebuffsById.ContainsKey(id)) DebuffsById.Add(id, new DebuffInternal(id));
                    return DebuffsById[id];
                }
            }

        }

        public class TalentProxy
        {
            public class Talent
            {
                private string _name;

                private bool? _enabled = null;

                public Talent(string name)
                {
                    this._name = name;
                }

                public bool Enabled
                {
                    get
                    {
                        if (_enabled == null) _enabled = StyxWoW.Me.GetLearnedTalents().Count(a => a.Name == _name) > 0;
                        return _enabled.Value;
                    }
                }

            }

            public void Reset()
            {
                _talents.Clear();
            }

            private Dictionary<String, Talent> _talents = new Dictionary<string, Talent>();

            public TalentProxy.Talent this[String name]
            {
                get
                {
                    if (!_talents.ContainsKey(name)) _talents.Add(name, new Talent(name));
                    return _talents[name];
                }
            }
        }

        public class TargetProxy
        {
            public HealthProxy Health = new HealthProxy(() => StyxWoW.Me.CurrentTarget);
            public int TimeToDie = 3600;
        }

        public class HealthProxy
        {

            public delegate WoWUnit GetUnitDelegate();

            public GetUnitDelegate GetUnit;

            public HealthProxy(GetUnitDelegate del)
            {
                GetUnit = del;
            }


            public double Percent
            {
                get { return StyxWoW.Me.HealthPercent; }
            }

            public int Missing
            {
                get { return GetUnit() != null ? (int)(GetUnit().MaxHealth - GetUnit().CurrentHealth) : 0; }
            }

            public int Max
            {
                get { return GetUnit() != null ? (int)(GetUnit().MaxHealth) : 0; }
            }

            public int Current
            {
                get { return GetUnit() != null ? (int)(GetUnit().CurrentHealth) : 0; }
            }

            public static bool operator <(HealthProxy h1, int val)
            {
                return h1.GetUnit() != null && h1.Current < val;
            }

            public static bool operator >(HealthProxy h1, int val)
            {
                return h1.GetUnit() != null && h1.Current > val;
            }

            public static bool operator <=(HealthProxy h1, int val)
            {
                return h1.GetUnit() != null && h1.Current <= val;
            }

            public static bool operator >=(HealthProxy h1, int val)
            {
                return h1.GetUnit() != null && h1.Current >= val;
            }

            public static bool operator !=(HealthProxy h1, int val)
            {
                return h1.GetUnit() != null ? h1.Current != val : false;
            }

            public static bool operator ==(HealthProxy h1, int val)
            {
                return h1.GetUnit() != null ? h1.Current == val : false;
            }

            public static int operator -(int val, HealthProxy h1)
            {
                return h1.GetUnit() != null ? val - h1.Current : 0;
            }
            public static int operator +(int val, HealthProxy h1)
            {
                return h1.GetUnit() != null ? val + h1.Current : 0;
            }

        }

        public class ChiProxy
        {

            public delegate WoWUnit GetUnitDelegate();

            public GetUnitDelegate GetUnit;

            public ChiProxy(GetUnitDelegate del)
            {
                GetUnit = del;
            }

            public int Missing
            {
                get { return Max - Current; }
            }

            public int Max
            {
                get { return (int)GetUnit().MaxChi; }
            }

            public int Current
            {
                get { return (int)GetUnit().CurrentChi; }
            }

            public static bool operator <(ChiProxy h1, int val)
            {
                return h1.Current < val;
            }

            public static bool operator >(ChiProxy h1, int val)
            {
                return h1.Current > val;
            }

            public static bool operator <=(ChiProxy h1, int val)
            {
                return h1.Current <= val;
            }

            public static bool operator >=(ChiProxy h1, int val)
            {
                return h1.Current >= val;
            }

            public static bool operator !=(ChiProxy h1, int val)
            {
                return h1.Current != val;
            }

            public static bool operator ==(ChiProxy h1, int val)
            {
                return h1.Current == val;
            }

            public static int operator -(int val, ChiProxy h1)
            {
                return val - h1.Current;
            }
            public static int operator +(int val, ChiProxy h1)
            {
                return val + h1.Current;
            }
        }

        public class EnergyProxy
        {

            public delegate WoWUnit GetUnitDelegate();

            public GetUnitDelegate GetUnit;

            public EnergyProxy(GetUnitDelegate del)
            {
                GetUnit = del;
            }


            public double Percent
            {
                get { return StyxWoW.Me.EnergyPercent; }
            }

            public int Missing
            {
                get { return GetUnit() != null ? (int)(GetUnit().MaxEnergy - GetUnit().CurrentEnergy) : 0; }
            }

            public int Max
            {
                get { return GetUnit() != null ? (int)(GetUnit().MaxEnergy) : 0; }
            }

            public double TimeToMax
            {
                get { return Missing / Regen; }
            }

            public int Current
            {
                get { return GetUnit() != null ? (int)(GetUnit().CurrentEnergy) : 0; }
            }

            public static bool operator <(EnergyProxy h1, int val)
            {
                return h1.GetUnit() != null && h1.Current < val;
            }

            public static bool operator >(EnergyProxy h1, int val)
            {
                return h1.GetUnit() != null && h1.Current > val;
            }

            public static bool operator <=(EnergyProxy h1, int val)
            {
                return h1.GetUnit() != null && h1.Current <= val;
            }

            public static bool operator >=(EnergyProxy h1, int val)
            {
                return h1.GetUnit() != null && h1.Current >= val;
            }

            public static bool operator !=(EnergyProxy h1, int val)
            {
                return h1.GetUnit() != null ? h1.Current != val : false;
            }

            public static bool operator ==(EnergyProxy h1, int val)
            {
                return h1.GetUnit() != null ? h1.Current == val : false;
            }

            public static int operator -(int val, EnergyProxy h1)
            {
                return h1.GetUnit() != null ? val - h1.Current : 0;
            }
            public static int operator +(int val, EnergyProxy h1)
            {
                return h1.GetUnit() != null ? val + h1.Current : 0;
            }

            private double _regen;

            public void Pulse()
            {
                _regen = Lua.GetReturnVal<double>(
                        "inactiveRegen, activeRegen = GetPowerRegen(); return activeRegen;", 0);
            }

            public double Regen
            {
                get { return _regen; }

            }
        }

        public class RageProxy
        {

            public delegate WoWUnit GetUnitDelegate();

            public GetUnitDelegate GetUnit;

            public RageProxy(GetUnitDelegate del)
            {
                GetUnit = del;
            }


            public double Percent
            {
                get { return StyxWoW.Me.EnergyPercent; }
            }

            public int Missing
            {
                get { return GetUnit() != null ? (int)(GetUnit().MaxEnergy - GetUnit().CurrentEnergy) : 0; }
            }

            public int Max
            {
                get { return GetUnit() != null ? (int)(GetUnit().MaxEnergy) : 0; }
            }

            public double TimeToMax
            {
                get { return Missing / Regen; }
            }

            public int Current
            {
                get { return GetUnit() != null ? (int)(GetUnit().CurrentEnergy) : 0; }
            }

            public static bool operator <(RageProxy h1, int val)
            {
                return h1.GetUnit() != null && h1.Current < val;
            }

            public static bool operator >(RageProxy h1, int val)
            {
                return h1.GetUnit() != null && h1.Current > val;
            }

            public static bool operator <=(RageProxy h1, int val)
            {
                return h1.GetUnit() != null && h1.Current <= val;
            }

            public static bool operator >=(RageProxy h1, int val)
            {
                return h1.GetUnit() != null && h1.Current >= val;
            }

            public static bool operator !=(RageProxy h1, int val)
            {
                return h1.GetUnit() != null ? h1.Current != val : false;
            }

            public static bool operator ==(RageProxy h1, int val)
            {
                return h1.GetUnit() != null ? h1.Current == val : false;
            }

            public static int operator -(int val, RageProxy h1)
            {
                return h1.GetUnit() != null ? val - h1.Current : 0;
            }
            public static int operator +(int val, RageProxy h1)
            {
                return h1.GetUnit() != null ? val + h1.Current : 0;
            }

            public double Regen
            {
                get
                {
                    return 12;
                    /*return Lua.GetReturnVal<double>(
                        "inactiveRegen, activeRegen = GetPowerRegen(); return activeRegen;", 0);*/
                }

            }
        }    



    }
}
